#include "PrivateBus_port.h"
#include "ModBusToPrivateBus_CRC.h"

/*
 * 从机私有协议需要提供的外部接口（功能部分）
 * 需要实现这些函数，库内部需要用到
 * 可以通过函数指针提供，也可以通过一下接口函数实现提供
 * 目前只支持单一主机或者单一从机，多主机多从机需要重新封装库。
 *
 * 外设：
 * ADC数据采集数据接口
 * INT：开启关闭外部中断接口
 * UART：串口发送数据接口
 * BUSY：总线状态读取函数
 *
 * */
uint8_t *PrivateBus_Uart_Tx_Buffer=NULL;
uint16_t PrivateBus_Uart_Tx_Buffer_Len;

uint16_t PrivateBus_Keep_Reg[2]={1,10};
//保持寄存器：通讯波特率 延迟发送时间

uint16_t ModBus_Slave_Message_Count=0;

/**
  * @bried  串口发送函数接口
  * @note   调用后直接发送，主机从机都是这个接口。
  * @param  None
  * @retval None
  */
void PB_Send_Date(uint8_t* _data,uint16_t _len){
    Uart1_Send(_data,_len);
}
/**
  * @bried  设置控制LED状态灯状态
  * @note   None
  * @param  None
  * @retval None
  */
void PB_Set_Mcu_Led(PB_LED_STATE _state){
    LED_MCU_SET((_state==PB_LED_STATE_ON)?LED_SATE_ON:LED_SATE_OFF);
}
/**
  * @bried  设置控制LED总线灯状态
  * @note   None
  * @param  None
  * @retval None
  */
void PB_Set_Bus_Led(PB_LED_STATE _state){
     LED_BUS_SET((_state==PB_LED_STATE_ON)?LED_SATE_ON:LED_SATE_OFF);
}
/** 
  * @bried  硬件CRC校验
  * @note   None
  * @param  None
  * @retval None
  */
void PB_Get_CRC(uint8_t* _data,uint16_t _len,uint8_t* _res_bit_l,uint8_t* _res_bit_h){
    GetModbusCRC16(_data,_len,_res_bit_l,_res_bit_h);
}

/**
  * @bried  读取保持寄存器
  * @note   None
  * @param  _reg：寄存器地址
  * @param  _len：访问的数量
  * @param  _res：读取寄存器返回的值
  * @retval None
  */
void PB_Port_03(uint16_t _reg,uint16_t _len,uint8_t* _res){
    if (_reg>2)return;
    uint8_t* reg=(uint8_t*)PrivateBus_Keep_Reg;
    for (int i = _reg; i < _len; ++i) {
        _res[i]=reg[i];
    }
}
/**
  * @bried  写单个保持寄存器
  * @note   None
  * @param  _reg：寄存器地址
  * @param  _data：待设置的数据
  * @retval None
  */
void PB_Port_06(uint16_t _reg,uint16_t _data){
    if (_reg>1)return;
    PrivateBus_Keep_Reg[_reg]=_data;
    if (_reg==0){//通讯波特率
        USART1->BRR=_data;
    } else if (_reg==1){//通讯延迟时间
        ModBus_CallBack_delay=_data;
    }
}
/**
  * @bried  错误诊断
  * @note   08命令字作为拓展版挂载时，有私有主机代理08命令字记录功能
  * @param  _mode：子功能码
  * @param  _rx_data：接收到的数据
  * @param  _tx_data:待返回的数据段
  * @retval None
  */
void PB_Port_08(uint16_t _mode,uint16_t _rx_data,uint8_t* _tx_data){
    switch (_mode) {
//        case 0x0000:break;//回送诊断寄存器（Return Query Data）
//        case 0x0001:break;//重启通信链路（Restart Communications Option）
//        case 0x0002:break;//返回事件计数器（Return Diagnostic Register）
//        case 0x0003:break;//更改ASCII模式的波特率（Change ASCII Input Delimiter）
//        case 0x0004:break;//强制监听仅模式（Force Listen Only Mode）
        case 0x000A://清除计数器和诊断寄存器（Clear Counters and Diagnostic Register）
            ModBus_Slave_Message_Count=0;
            break;
//        case 0x000B:break;//返回总消息计数（Return Bus Message Count）
//        case 0x000C:break;//返回总CRC错误计数（Return Bus Communication Error Count）
//        case 0x000D:break;//返回总异常响应计数（Return Bus Exception Error Count）
        case 0x000E://返回总报文计数（Return Slave Message Count）
            _tx_data[0]=ModBus_Slave_Message_Count>>8;
            _tx_data[1]=ModBus_Slave_Message_Count&0x00FF;
            break;
//        case 0x000F:break;//返回总无响应计数（Return Slave No Response Count）
//        case 0x0010:break;//返回总写计数（Return Slave NAK Count）
//        case 0x0011:break;//返回总忙计数（Return Slave Busy Count）
//        case 0x0012:break;//返回总错误计数（Return Bus Character Overrun Count）
        default:
            break;
    }
}
/**
  * @bried  写多个保持寄存器
  * @note   保持寄存器为16位，传入uint8需要手动解析为uint16，其中前面为高字节，后面为低字节。_len为uint8的数量
  * @param  _reg：寄存器地址
  * @param  _data：待写入的数据
  * @retval None
  */
void PB_Port_10(uint16_t _reg,uint16_t _len,uint8_t const* _data){
    for (int i = _reg; i < _len; ++i) {
        PB_Port_06(i, _data[i]);
    }
}
